var NUMBER_OF_PARTICLE = 500;
var g_particlePool = new Array();

function Particle(context) {
	this.m_context = context;
	
	this.Reset = function () {
		// Life
		this.m_start = false;
		this.m_lifeTime = 0;
		this.m_time = 0;
		
		// Moving
		this.m_x = 0;
		this.m_y = 0;
		this.m_moveSpeedX = 0;
		this.m_moveSpeedY = 0;
		this.m_resistant = 0;
		this.m_gravity = 0;
		
		// Rotating
		this.m_angle = 0;
		this.m_rotateSpeed = 0;
		this.m_rotateResistant = 0;
		this.m_rotateAcceleration = 0;
		
		// Fade
		this.m_alpha = 1;
		this.m_fadeSpeed = 0;
		
		// Image
		this.m_sourceRectArray = [];
		this.m_frameLength = 0;
		this.m_w = 0;
		this.m_h = 0;
		this.m_drawAdd = false;
	}
	
	this.Reset();
	
	var frameCount = 0;
	var currentFrame = 0;
	this.Start = function () {
		this.m_start = true;
		this.m_time = 0;
		currentFrame = 0;
	}
	
	this.Update = function () {
		if (this.m_start) {
			// Update life time
			this.m_time += g_deltaTime;
			if (this.m_time >= this.m_lifeTime) {
				this.m_start = false;
			}
			
			// Update animation
			frameCount += g_deltaTime;
			if (frameCount >= this.m_frameLength) {
				frameCount -= this.m_frameLength;
				currentFrame ++;
				if (currentFrame >= this.m_sourceRectArray.length) {
					currentFrame = 0;
				}
			}
			
			// Air resistant
			var resistant = this.m_resistant * g_deltaTime;
			
			if (this.m_moveSpeedX > 0) {
				this.m_moveSpeedX -= resistant;
				if (this.m_moveSpeedX < 0) this.m_moveSpeedX = 0;
			}
			else if (this.m_moveSpeedX < 0) {
				this.m_moveSpeedX += resistant;
				if (this.m_moveSpeedX > 0) this.m_moveSpeedX = 0;
			}
			
			if (this.m_moveSpeedY > 0) {
				this.m_moveSpeedY -= resistant;
				if (this.m_moveSpeedY < 0) this.m_moveSpeedY = 0;
			}
			else if (this.m_moveSpeedY < 0) {
				this.m_moveSpeedY += resistant;
				if (this.m_moveSpeedY > 0) this.m_moveSpeedY = 0;
			}
			
			// Gravity
			this.m_moveSpeedY += this.m_gravity * g_deltaTime;
			
			// Move
			this.m_x += this.m_moveSpeedX * g_deltaTime;
			this.m_y += this.m_moveSpeedY * g_deltaTime;
			
			
			// Rotate air resistant
			resistant = this.m_rotateResistant * g_deltaTime;
			if (this.m_rotateSpeed > resistant) {
				this.m_rotateSpeed -= resistant;
			}
			else if (this.m_rotateSpeed < -resistant) {
				this.m_rotateSpeed += resistant;
			}
			else {
				this.m_rotateSpeed = 0;
			}
			
			// Rotate acceleration
			if (this.m_rotateAcceleration != 0) {
				this.m_rotateSpeed += this.m_rotateAcceleration * g_deltaTime;
			}
			
			this.m_angle += this.m_rotateSpeed * g_deltaTime;
			if (this.m_angle > 360) this.m_angle -= 360;
			if (this.m_angle < 360) this.m_angle += 360;
			
			// Fade
			this.m_alpha += this.m_fadeSpeed * g_deltaTime;
		}
	}
	
	
	this.Draw = function () {
		if (this.m_start) {
			var sourceRect = this.m_sourceRectArray[currentFrame];
			
			if (this.m_drawAdd) g_graphicEngine.SetDrawModeAddActive (this.m_context, true);
			g_graphicEngine.Draw (this.m_context, sourceRect.m_id, sourceRect.m_x, sourceRect.m_y, sourceRect.m_w, sourceRect.m_h, this.m_x, this.m_y, this.m_w, this.m_h, this.m_alpha, 0, 0, this.m_angle);
			if (this.m_drawAdd) g_graphicEngine.SetDrawModeAddActive (this.m_context, false);
		}
	}
	
	
	this.CloneFrom = function (rhs) {
		this.m_context = rhs.m_context;
		
		// Life
		this.m_start = rhs.m_start;
		this.m_lifeTime = rhs.m_lifeTime;
		this.m_time = rhs.m_time;
		
		// Moving
		this.m_x = rhs.m_x;
		this.m_y = rhs.m_y;
		this.m_moveSpeedX = rhs.m_moveSpeedX;
		this.m_moveSpeedY = rhs.m_moveSpeedY;
		this.m_resistant = rhs.m_resistant;
		this.m_gravity = rhs.m_gravity;
		
		// Rotating
		this.m_angle = rhs.m_angle;
		this.m_rotateSpeed = rhs.m_rotateSpeed;
		this.m_rotateResistant = rhs.m_rotateResistant;
		this.m_rotateAcceleration = rhs.m_rotateAcceleration;
		
		// Fade
		this.m_alpha = rhs.m_alpha;
		this.m_fadeSpeed = rhs.m_fadeSpeed;
		
		// Image
		this.m_sourceRectArray = rhs.m_sourceRectArray;
		this.m_frameLength = rhs.m_frameLength;
		this.m_w = rhs.m_w;
		this.m_h = rhs.m_h;
		this.m_drawAdd = rhs.m_drawAdd;
	}
}


function Emitter (particle) {
	// Instance
	var instance = this;
	var degToRad = 0.0174532925199433;
	
	// Clear all variable - reset
	this.Reset = function () {
		// Position
		this.m_x = 0;
		this.m_y = 0;
		this.m_w = 0;
		this.m_h = 0;
		
		// Life
		this.m_lifeTime = 0;
		this.m_time = 0;
		this.m_start = false;
		
		// Emit parameters
		this.m_emitForceMin = 0;
		this.m_emitForceMax = 0;
		this.m_emitAngleStart = 0;
		this.m_emitAngleEnd = 360;
		this.m_emitRate = 0;
		
		// Particle parameters
		this.m_randomizeScaleMin = 0;
		this.m_randomizeScaleMax = 0;
		this.m_randomizeAngleMin = 0;
		this.m_randomizeAngleMax = 0;
		this.m_randomizeLifeMin  = 0;
		this.m_randomizeLifeMax  = 0;
		this.m_randomizeRotateSpeedMin = 0;
		this.m_randomizeRotateSpeedMax = 0;
	}
	
	this.Reset();
	
	
	var emitCount = 0;
	
	this.Start = function () {
		this.m_start = true;
		this.m_time = 0;
		this.m_emitTime = 0;
	}
	
	
	
	this.Update = function () {
		if (this.m_start) {
			// Life
			this.m_time += g_deltaTime;
			if (this.m_lifeTime > 0) {
				if (this.m_time >= this.m_lifeTime) {
					this.m_start = false;
					return;
				}
			}
			
			var emitNumber = 0;
			emitCount += g_deltaTime;
			emitNumber = (emitCount * this.m_emitRate) >> 0;
			if (emitNumber > 0) {
				emitCount -= emitNumber / this.m_emitRate;
			}
			
			for (var i=0; i<emitNumber; i++) {
				var found = false;
				var tempParticle;
				
				for (var j=0; j<g_particlePool.length; j++) {
					if (g_particlePool[j]) {
						if (!g_particlePool[j].m_start) {
							tempParticle = g_particlePool[j];
							found = true;
							break;
						}
					}
				}
				
				if (!found) {
					if (g_particlePool.length == NUMBER_OF_PARTICLE) {
						return;
					}
					tempParticle = new Particle();
					g_particlePool.push(tempParticle);
				}
				
				tempParticle.CloneFrom (particle);
				tempParticle.Start ();
				
				// Force and direction
				var randomAngle = Math.random() * (this.m_emitAngleEnd - this.m_emitAngleStart) + this.m_emitAngleStart;
					randomAngle = randomAngle % 360;
					randomAngle *= degToRad;
				var randomForce = Math.random() * (this.m_emitForceMax - this.m_emitForceMin) + this.m_emitForceMin;
				tempParticle.m_moveSpeedX = Math.cos(randomAngle) * randomForce;
				tempParticle.m_moveSpeedY = - Math.sin(randomAngle) * randomForce;
				
				// Position
				if (this.m_w == 0 && this.m_h == 0) {
					tempParticle.m_x = this.m_x;
					tempParticle.m_y = this.m_y;
				}
				else {
					var randomX = this.m_x + Math.random() * this.m_w;
					var randomY = this.m_y + Math.random() * this.m_h;
					tempParticle.m_x = randomX;
					tempParticle.m_y = randomY;
				}
				
				// Life
				if (this.m_randomizeLifeMax == 0 && this.m_randomizeLifeMin == 0) {}
				else {
					var randomLife  = Math.random() * (this.m_randomizeLifeMax - this.m_randomizeLifeMin) + this.m_randomizeLifeMin;
					tempParticle.m_lifeTime =  randomLife;
				}
				
				// Angle
				if (this.m_randomizeAngleMax == 0 && this.m_randomizeAngleMin == 0) {}
				else {
					var randomAngle  = Math.random() * (this.m_randomizeAngleMax - this.m_randomizeAngleMin) + this.m_randomizeAngleMin;
					tempParticle.angle = randomAngle;
				}
				
				// Rotate speed
				if (this.m_randomizeRotateSpeedMin == 0 && this.m_randomizeRotateSpeedMax == 0) {}
				else {
					var randomSpeed  = Math.random() * (this.m_randomizeRotateSpeedMax - this.m_randomizeRotateSpeedMin) + this.m_randomizeRotateSpeedMin;
					tempParticle.rotateSpeed = randomSpeed;
				}
			}
		}
	}
}


function DrawParticles () {
	for (var i=0; i<g_particlePool.length; i++) {
		g_particlePool[i].Update();
		g_particlePool[i].Draw();
	}
}